package com.project.shiro;

//import com.project.common.utils.PublicUtils;
import com.project.common.utils.PublicUtils;
import com.project.entity.User;
import com.project.service.UserService;
//import com.project.service.base.cryptolib.CryptoApp;
import com.project.service.base.cryptolib.CryptoApp;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.ExcessiveAttemptsException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.authc.credential.HashedCredentialsMatcher;
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.concurrent.atomic.AtomicInteger;


/**
 *  自定义凭证匹配器
 *  可限制登录次数，如：5次出错，锁定10分钟
 */

public class RetryLimitHashedCredentialsMatcher extends HashedCredentialsMatcher {
    @Autowired
    @Lazy //延时加载（懒加载）
    private UserService userService;



    private static Cache<String, AtomicInteger> passwordRetryCache;

    private Logger log = LogManager.getLogger(getClass());

    @Autowired
    public RetryLimitHashedCredentialsMatcher(CacheManager cacheManager){
        passwordRetryCache = cacheManager.getCache("passwordRetryCache");
    }

    public static Cache<String, AtomicInteger> getPasswordRetryCache(){
        return passwordRetryCache;
    }

    @Override
    public boolean doCredentialsMatch(AuthenticationToken token, AuthenticationInfo info) {
        boolean matches=false;

        //info 来自UserReal类doGetAuthenticationInfo方法的返回值

        String username = (String) token.getPrincipal();
        //retry count + 1
        AtomicInteger retryCount = passwordRetryCache.get(username);
        log.info("retryCount>>>>"+passwordRetryCache.get(username));
        if (retryCount == null) {
            retryCount = new AtomicInteger(0);
            passwordRetryCache.put(username, retryCount);
        }
        if (retryCount.incrementAndGet() > 5) {
            //if retry count > 5 throw
            throw new ExcessiveAttemptsException();
        }

        //shiro提供的密码验证
        // matches = super.doCredentialsMatch(token, info);

        //自定义密码验证:start
        //UsernamePasswordToken封装登录用户名及密码
        UsernamePasswordToken token2 = (UsernamePasswordToken) token;
        User user = userService.findByUserName(token2.getUsername());

        log.info("password==="+String.valueOf(token2.getPassword()));
        String salt="";
        if(user!=null)
            salt=user.getSalt();
        //将token中的原始密码进加密
        Object tokenCredentials = null;
        try {
            tokenCredentials = CryptoApp.PwdTransValue(String.valueOf(token2.getPassword()).getBytes(), PublicUtils.hexStringToBytes(salt));
        } catch (Exception e) {
            e.printStackTrace();
            return false;
        }

        //获取db中的用户密码
        Object accountCredentials = getCredentials(info);

        //将原始密码加密与取自DB的用户密码校验，内容一致就返回true,不一致就返回false
        matches = equals(tokenCredentials, accountCredentials);
        //自定义密码验证:end

        if (matches) {
            //clear retry count
            passwordRetryCache.remove(username);
        }


        return matches;
    }

}
